/*
 * Copyright (c) 2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.libermundi.theorcs.core.util;

import org.libermundi.theorcs.core.exceptions.ValueNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

public final class JsonUtils {
	private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class);
	
	private JsonUtils() {}
	
	/**
	 * Parse a Json {@link String} and returns a {@link JsonElement}
	 */	
	public static JsonElement parse(String json) {
		return new JsonParser().parse(json);
	}
	
	/**
	 * Method to retrieve a Value from a Json. Base on the {@link Gson} library
	 * @param json the json formatted {@link String}
	 * @param dottedKey the key in "dotted" format (ex ! 'a.b.c' )
	 * @return value
	 * @throws ValueNotFoundException is the key does not match any existing value
	 */
	public static String getKey(String json, String dottedKey)  throws ValueNotFoundException {
		JsonElement tree = parse(json);
		return JsonUtils.getKey(tree, dottedKey);
	}
	
	/**
	 * Same as {@link JsonUtils#getKey(String, String)} but more convenient if many keys have to be found in the same Json String
	 * as this method skips the Parsing of the Json String
	 *  
	 * @param jsonTree
	 * @param dottedKey
	 * @return the value or null
	 * @throws ValueNotFoundException
	 */
	public static String getKey(JsonElement jsonTree, String dottedKey) throws ValueNotFoundException {
		String result = null;
		if(jsonTree.isJsonObject()) {
			result = getKey(jsonTree.getAsJsonObject(), dottedKey);
		} else if (jsonTree.isJsonArray()) {
			for(JsonElement element : jsonTree.getAsJsonArray()) {
				try{
					result = getKey(element, dottedKey);
				} catch (ValueNotFoundException e) {
					if(logger.isDebugEnabled()) {
						logger.debug(e.getMessage());
					}
				}
			}
		}
		
		if(logger.isDebugEnabled()) {
			if(result != null) {
				logger.debug(dottedKey + " ==> " + result);
			} else {
				logger.debug(dottedKey + " ==> Value not Found");
			}
		}
		
		return result;
	}
	
	private static String getKey(JsonObject jsonObject, String dottedKey) throws ValueNotFoundException {
		String key = StringListUtils.listFirst(dottedKey, ".");
		JsonElement result = jsonObject.get(key);
		if(result != null) {
			if( result.isJsonObject() || result.isJsonArray()) { 
				if( StringListUtils.listLenght(dottedKey, ".") > 1 ) {
					return getKey(result, StringListUtils.listDeleteAt(dottedKey, 0, "."));
				}
				throw new ValueNotFoundException();
			}
			return result.getAsString();
		}
		throw new ValueNotFoundException();
	}
}
